package sysService

import (
	"context"
	"fmt"
	"gitee.com/jokces/kit/enum"
	"gitee.com/jokces/kit/errc"
	sysModel "gitee.com/jokces/kit/global/admin/model"
	"gitee.com/jokces/kit/typ"
	"github.com/gin-gonic/gin"
	"strings"
	"time"
)

func (svc *Service) InsertFile(ctx context.Context, in sysModel.SysFileRecord) error {
	return svc.d.InsertFile(ctx, in)
}

func (svc *Service) GetFile(ctx context.Context, fileName string) (bool, sysModel.SysFileRecord, error) {
	return svc.d.GetFile(ctx, fileName)
}

// ParamList 系统参数
func (svc *Service) ParamList(ctx *gin.Context, in *sysModel.ParamListReq) (typ.ListResp, error) {
	rs := typ.ListResp{}
	//系统默认的参数是不能进行处理的
	count, params, err := svc.d.ParamList(ctx, &sysModel.SysParam{
		Key:    in.Key,
		Name:   in.Name,
		Status: in.Status,
		Typ:    1,
	}, &in.PageReq)
	if err != nil {
		return rs, err
	}
	rs.Count = count
	rs.List = params
	return rs, nil
}
func (svc *Service) DicList(ctx *gin.Context, in *sysModel.DicListReq) (typ.ListResp, error) {
	rs := typ.ListResp{}
	count, params, err := svc.d.DicList(ctx, &sysModel.SysDic{
		Key:    in.Key,
		Value:  in.Name,
		Status: enum.ABLE,
	}, in.PageGet())
	if err != nil {
		return rs, err
	}
	arr := make([]*sysModel.DicVo, 0)
	for _, param := range params {
		arr = append(arr, &sysModel.DicVo{
			Key:   param.UniqueKey,
			Value: param.Value,
		})
	}
	rs.Count = count
	rs.List = arr
	return rs, nil
}
func (svc *Service) DicValueOne(ctx *gin.Context, key string) (string, error) {
	val, err := svc.r.KeyWithStringCache(24*time.Hour)(ctx, fmt.Sprintf("DIC:%v", key), func() (interface{}, error) {
		_, dic, err := svc.d.DicOne(ctx, &sysModel.SysDic{
			UniqueKey: key,
		})
		if err != nil {
			return "", err
		}
		return dic.Value, nil
	})
	if err != nil {
		return "", err
	}
	return val, nil
}
func (svc *Service) DictAdminList(ctx *gin.Context, in *sysModel.DicListReq) (typ.ListResp, error) {
	rs := typ.ListResp{}
	count, params, err := svc.d.DicList(ctx, &sysModel.SysDic{
		Key:    in.Key,
		Value:  in.Name,
		Status: in.Status,
	}, in.PageGet())
	if err != nil {
		return rs, err
	}
	rs.Count = count
	rs.List = params
	return rs, nil
}
func (svc *Service) DicAreaList(ctx *gin.Context, in *sysModel.AreaListReq) ([]*sysModel.AreaListResp, error) {
	rs := make([]*sysModel.AreaListResp, 0)
	req := &sysModel.SysArea{}
	if in.All {
		req.ParentId = -1
	} else {
		req.ParentId = in.ParentId
	}
	params, err := svc.d.AreaList(ctx, req)
	if err != nil {
		return rs, err
	}
	for _, param := range params {
		rs = append(rs, &sysModel.AreaListResp{
			Id:       param.Id,
			ParentId: param.ParentId,
			AreaName: param.AreaName,
		})
	}
	return rs, nil
}
func (svc *Service) ParamSaveOrUpdate(ctx context.Context, in *sysModel.ParamEditReq, sess sysModel.AdminUserToken) error {
	dto := sysModel.SysParam{
		Key:    in.Key,
		Name:   in.Name,
		Value:  in.Value,
		Memo:   in.Memo,
		Status: in.Status,
	}
	if in.Id > 0 {
		exist, param, err := svc.d.ParamGetOne(ctx, &sysModel.SysParam{Id: in.Id})
		if err != nil {
			return err
		}
		if !exist {
			return errc.ErrParamInvalid.MultiMsg("key不存在")
		}

		if param.Typ == 0 && !sess.RootRole() {
			return errc.ErrParamInvalid.MultiMsg("root can do this")
		}

		if err := svc.d.GetDao().TxUpdate(nil, param.Id, dto, []string{"`name`", "`value`", "memo", "`status`"}); err != nil {
			return err
		}
		return nil
	}

	exist, _, err := svc.d.ParamGetOne(ctx, &sysModel.SysParam{Key: in.Key})
	if err != nil {
		return err
	}
	if exist {
		return errc.ErrParamInvalid.MultiMsg("key exists")
	}

	if err := svc.d.GetDao().TxInsert(nil, dto); err != nil {
		return err
	}
	return nil
}

// UserActionExist 用户的权限数据是否存在
func (svc *Service) UserActionExist(sess *sysModel.AdminUserToken, api string) (bool, error) {
	if sess.RootRole() {
		return true, nil
	}
	key := fmt.Sprintf("%v:%v", sysModel.AdminActions, sess.RoleId)
	result, err := svc.r.KeyWithStringCache(24*time.Hour)(context.Background(), key, func() (interface{}, error) {
		list, err := svc.d.RoleActionList(context.Background(), sess.RoleId)
		return list, err
	})
	if err != nil {
		return false, err
	}
	if result == "" {
		return false, nil
	}
	actions := make([]*sysModel.SysActionBo, 0)
	_ = enum.ToObject(result, &actions)
	for _, action := range actions {
		if strings.Contains(api, action.Api) {
			return true, nil
		}
	}
	return false, nil
}

// OperatePageList ParamList 操作日志
func (svc *Service) OperatePageList(ctx *gin.Context, in *sysModel.OptListReq) (typ.ListResp, error) {
	rs := typ.ListResp{}
	//系统默认的参数是不能进行处理的
	count, params, err := svc.d.SysOperateLogList(ctx, &sysModel.SysOperateLog{
		Opt:      in.Opt,
		TraceId:  in.TraceId,
		UserName: in.UserName,
	}, &in.PageReq, &in.TimeStringReq)
	if err != nil {
		return rs, err
	}
	rs.Count = count
	rs.List = params
	return rs, nil
}
func (svc *Service) OperateInsert(in *sysModel.SysOperateLog) error {
	if in.ResponseBody != "" {
		out := &sysModel.Rs{}
		_ = enum.ToObject(in.ResponseBody, out)
		in.TraceId = out.TraceId
		in.BizStatus = out.Code
		in.Message = out.Message
	}
	err := svc.d.GetDao().TxInsert(nil, in)
	return err
}

func (svc *Service) ClassifyList(ctx *gin.Context, in *sysModel.ClassifyListReq) (typ.ListResp, error) {
	rs := typ.ListResp{}
	count, params, err := svc.d.ClassifyList(ctx, &sysModel.SysClassify{
		ParentId: in.ParentId,
		Name:     in.Name,
		Status:   in.Status,
		Code:     in.Code,
	}, in.PageReq)
	if err != nil {
		return rs, err
	}
	rs.Count = count
	rs.List = params
	return rs, nil
}
func (svc *Service) AddClassify(ctx *gin.Context, in *sysModel.ClassifyAddReq) error {
	var parent *sysModel.SysClassify
	if in.ParentId > 0 {
		exist, classify, err := svc.d.ClassifyOne(ctx, &sysModel.SysClassify{Id: in.ParentId})
		if err != nil {
			return err
		}
		if !exist {
			return errc.ErrParamInvalid.MultiMsg("未找到对应的分类")
		}
		parent = classify
	}

	if err := svc.d.ClassifyInsert(ctx, &sysModel.SysClassify{
		ParentId: in.ParentId,
		Name:     in.Name,
		Extra:    in.Extra,
		Status:   in.Status,
	}, parent); err != nil {
		return err
	}
	return nil
}
func (svc *Service) EditClassify(ctx *gin.Context, in *sysModel.ClassifyEditReq) error {
	exist, classify, err := svc.d.ClassifyOne(ctx, &sysModel.SysClassify{Id: in.Id})
	if err != nil {
		return err
	}
	if !exist {
		return errc.ErrParamInvalid.MultiMsg("未找到对应的分类")
	}
	if err := svc.d.GetDao().TxBeanUpdate(nil, classify.Id, &sysModel.SysClassify{
		Name:   in.Name,
		Extra:  in.Extra,
		Status: in.Status,
	}); err != nil {
		return err
	}
	return nil
}
func (svc *Service) DelClassify(ctx *gin.Context, id int64) error {
	row, _, err := svc.d.ClassifyList(ctx, &sysModel.SysClassify{ParentId: id}, nil)
	if err != nil {
		return err
	}
	if row > 0 {
		return errc.ErrParamInvalid.MultiMsg("请先删除子分类")
	}
	if err := svc.d.GetDao().TxUpdate(nil, id, &sysModel.SysClassify{
		IsDel: 1,
	}, []string{"is_del"}); err != nil {
		return err
	}
	return nil
}
